﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Data;
using System.Reflection;
using NCS.IConnect.CodeTable;
using NCS.IConnect.CodeTable.Web;

using JM.JCY.BusinessEntity;
using System.Web.UI.WebControls;
using System.IO;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using System.Net.Mail;

namespace JM.JCY.Common
{
    public class OCPUtility
    {
        /// <summary>
        /// An utility that perform deep cloning of an object.
        /// </summary>
        /// <typeparam name="Source">Source</typeparam>
        /// <typeparam name="Result">Destination</typeparam>
        public static class ObjectCloner<Source, Result>
            where Source : class, new()
            where Result : class, new()
        {
            public static Result DeepClone(Source obj, params string[] ignores)
            {
                if (obj == null)
                    return null;

                Result result = new Result();

                foreach (PropertyInfo info in obj.GetType().GetProperties())
                {
                    //check for ignores
                    if (ignores != null && ignores.Contains(info.Name))
                        continue;

                    foreach (PropertyInfo rInfo in result.GetType().GetProperties())
                    {
                        if (info.Name.ToLowerInvariant().Equals(rInfo.Name.ToLowerInvariant()))
                        {
                            rInfo.SetValue(result, info.GetValue(obj, null), null);
                            break;
                        }
                    }
                }
                return result;
            }
        }

        /// <summary>
        /// A generic utility that maps data from a DataTable/Typed DataTable to a List of DTOs
        /// </summary>
        /// <typeparam name="TDTO">DTO type</typeparam>
        public static class DTOTableMapper<TDTO> where TDTO : class, new()
        {
            /// <summary>
            /// Maps data from DataTable to IList of DTOs
            /// </summary>
            /// <param name="Table">The DataTable to map</param>
            /// <returns>Returns a list of data mapped objects</returns>
            public static IList<TDTO> MapToDTO(DataTable Table)
            {
                //return value
                IList<TDTO> dtoList = new List<TDTO>();

                if (Table != null && Table.Rows.Count > 0)
                {
                    try
                    {
                        //iterate rows
                        foreach (DataRow row in Table.Rows)
                        {
                            //declare new DTO instance
                            TDTO newDTO = new TDTO();

                            //get DTO properties
                            PropertyInfo[] properties = typeof(TDTO).GetProperties();

                            //iterate column
                            for (var i = 0; i < row.Table.Columns.Count; i++)
                            {
                                //value type
                                object value = row[i];
                                //skip to next if null
                                if (value == null || value == DBNull.Value)
                                    continue;

                                //column name
                                var colName = Table.Columns[i].ColumnName;

                                //iterate property info of DTO
                                foreach (PropertyInfo pInfo in properties)
                                {
                                    //checks if column name and property name matches
                                    if (colName == pInfo.Name)
                                    {
                                        //sets value
                                        pInfo.SetValue(newDTO, row[i], null);
                                    }
                                }
                            }

                            //adds new DTO to return value
                            dtoList.Add(newDTO);
                        }
                    }
                    catch (DataException dex)
                    {
                        throw dex;
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }
                return dtoList;
            }

            /// <summary>
            /// Maps data from a single DataRow to a DTO
            /// </summary>
            /// <param name="?"></param>
            /// <returns></returns>
            public static TDTO MapToDTO(DataRow Row)
            {
                //declare new DTO instance
                TDTO newDTO = new TDTO();

                if (Row == null)
                    return newDTO;

                //get DTO properties
                PropertyInfo[] properties = typeof(TDTO).GetProperties();

                foreach (DataColumn col in Row.Table.Columns)
                {
                    if (Row[col.ColumnName] == null || Row[col.ColumnName] == DBNull.Value)
                        continue;

                    foreach (PropertyInfo info in properties)
                    {
                        if (col.ColumnName.Equals(info.Name))
                        {
                            info.SetValue(newDTO, Row[col.ColumnName], null);
                            break;
                        }
                    }
                }

                return newDTO;
            }


            private static void CreateColumns(ref DataTable Table, TDTO DTO)
            {
                //get properties
                PropertyInfo[] pInfos = DTO.GetType().GetProperties();
                Table.Columns.AddRange(GetColumns(pInfos).ToArray());
            }

            private static IEnumerable<DataColumn> GetColumns(PropertyInfo[] pInfos)
            {
                foreach (PropertyInfo info in pInfos)
                {
                    DataColumn col = new DataColumn();
                    col.DataType = info.PropertyType;
                    col.ColumnName = info.Name;
                    yield return col;
                }
            }
        }

        // auto generate media player html codes
        public static string VideoPlayerGeneration(string mediaPlayerId, string videoUrl, string previewUrl, string width, string height)
        {
            string mediaHtml = "<a style='display: block; width:" + width + "; height:" + height + ";' id='" + mediaPlayerId + "'></a>";
            string JsScript = "<script type='text/javascript'>flowplayer('" + mediaPlayerId + @"', '/_layouts/NCS.OCP.Resource/scripts/flowplayer-3.2.7.swf', {

                onLoad: function () {
                    this.setVolume(30);
               },
                playlist: [
                    {
                      url: '" + previewUrl + @"',
                      scaling: 'orig'
                    },
                    {
                autoPlay: false,
                autoBuffering: true,
                url: '" + videoUrl + @"'
                     }
                ],
                onMouseOver: function () {
                    this.play();
                },
               onMouseOut: function () {
                    this.stop();
               }
             });
             </script>";
            return mediaHtml + JsScript;
        }

        //auto generate audio player html codes
        public static string AudioPlayerGeneration(string audioPlayerId, string audioUrl, string previewUrl, string width, string height)
        {
            string audioHtml = "<div id='" + audioPlayerId + "' style='display: block; width:" + width + "; height:" + height + ";'></div>";
            string JsScript = "<script>flowplayer('" + audioPlayerId + @"', '/_layouts/NCS.OCP.Resource/scripts/flowplayer-3.2.7.swf', {

                                                // fullscreen button not needed here
                                                plugins: {
                                                    controls: {
                                                        url: '/_layouts/NCS.OCP.Resource/scripts/flowplayer.controls-3.2.5.swf',
                                                        fullscreen: false,
                                                        height: 25,
                                                        autoHide: true
                                                    },

                                                    audio: {
                                                        url: '/_layouts/NCS.OCP.Resource/scripts/flowplayer.audio-3.2.2.swf'
                                                    }
                                                },

                                                clip: {

                                                    // optional: when playback starts close the first audio playback
                                                    onBeforeBegin: function () {
                                                        flowplayer('" + audioPlayerId + @"').close();
                                                    },
                                                    autoPlay: false,
                                                    autoBuffering: true,
                                                    url: '" + audioUrl + @"',
                                                    // cover image with scaling specified
                                                    coverImage: { url:'" + previewUrl + @"', scaling: 'orig' }
                                                },
                                                onMouseOver: function () {

                                                    this.play();

                                                },
                                                onMouseOut: function () {
                                                    this.stop();
                                                }
                                            });
                                        </script>";

            return audioHtml + JsScript;
        }

        public static void UpdateCommonFields(DataRow dataRow, string name)
        {
            DataTable dt = dataRow.Table;
            if (dt.Columns.Contains("LAST_UPDATED_BY") && (dataRow["LAST_UPDATED_BY"] == DBNull.Value))
                dataRow["LAST_UPDATED_BY"] = name;

            else if (dt.Columns.Contains("LastUpdatedBy") && (dataRow["LastUpdatedBy"] == DBNull.Value))
                dataRow["LastUpdatedBy"] = name;

            if (dt.Columns.Contains("LAST_UPDATED_TIME") && (dataRow["LAST_UPDATED_TIME"] == DBNull.Value))
                dataRow["LAST_UPDATED_TIME"] = DateTime.Now;

            else if (dt.Columns.Contains("LastUpdatedTime") && (dataRow["LastUpdatedTime"] == DBNull.Value))
                dataRow["LastUpdatedTime"] = DateTime.Now;

            if (dataRow.RowState != DataRowState.Modified && dataRow.RowState != DataRowState.Unchanged)
            {
                if (dt.Columns.Contains("TRANSACTION_ID"))
                    dataRow["TRANSACTION_ID"] = "temp";
                else if (dt.Columns.Contains("TransactionId"))
                    dataRow["TransactionId"] = "temp";

                if (dt.Columns.Contains("VERSION_NO"))
                    dataRow["VERSION_NO"] = 1;
                else if (dt.Columns.Contains("VersionNo"))
                    dataRow["VersionNo"] = 1;

                if (dt.Columns.Contains("CREATED_BY"))
                    dataRow["CREATED_BY"] = name;
                else if (dt.Columns.Contains("CreatedBy"))
                    dataRow["CreatedBy"] = name;

                if (dt.Columns.Contains("CREATED_TIME"))
                    dataRow["CREATED_TIME"] = DateTime.Now;
                else if (dt.Columns.Contains("CreatedTime"))
                    dataRow["CreatedTime"] = DateTime.Now;
            }
        }

        public static void PopulateListControl(ListControl control, DataTable dataSource, string textField, string valueField, string orderField, bool addEmptyRow)
        {
            control.DataTextField = textField;
            control.DataValueField = valueField;

            DataTable dt = dataSource.Copy();
            dt.DefaultView.Sort = orderField;

            control.Items.Clear();
            control.DataSource = dt;
            control.DataBind();

            if (addEmptyRow)
                control.Items.Insert(0, new ListItem(OCPConstant.DropdownlistEmptyText, string.Empty));
        }

        public static void PopulateListControlWithAllOption(ListControl control, DataTable dataSource, string textField, string valueField, string orderField)
        {
            control.DataTextField = textField;
            control.DataValueField = valueField;

            DataTable dt = dataSource.Copy();
            dt.DefaultView.Sort = orderField;

            control.Items.Clear();
            control.DataSource = dt;
            control.DataBind();

            control.Items.Insert(0, new ListItem(OCPConstant.DropdownlistAllText, string.Empty));
        }

        public static bool ExceptionHandle(string functionName, Exception ex)
        {
            try
            {
                string userName = Microsoft.SharePoint.SPContext.Current.Web.CurrentUser.LoginName;
                string logPath = System.Web.HttpContext.Current.Server.MapPath(OCPConstant.ErrorLogPath);
                if (Directory.Exists(logPath) == false)
                {
                    Directory.CreateDirectory(logPath);
                }
                string logFileName = DateTime.Today.ToString("ddMMyyyy") + ".txt";
                if (File.Exists(logPath + logFileName))
                {
                    StreamWriter sw = new StreamWriter(logPath + logFileName, true);
                    sw.WriteLine(DateTime.Now.ToString("HH:mm:ss").PadRight(10) + userName.PadRight(25) + functionName.PadRight(30) + ex.Message);
                    sw.Close();
                    sw.Dispose();
                }
                else
                {
                    StreamWriter sw = File.CreateText(logPath + logFileName);
                    sw.WriteLine("ExTime".PadRight(10) + "User Name".PadRight(25) + "Function Name".PadRight(30) + "Error Message");
                    sw.WriteLine(DateTime.Now.ToString("HH:mm:ss").PadRight(10) + userName.PadRight(25) + functionName.PadRight(30) + ex.Message);
                    sw.Close();
                    sw.Dispose();
                }
            }
            catch (Exception exp)
            {
                return false;
            }
            return true;
        }

        internal static string GetUserName()
        {

            return Microsoft.SharePoint.SPContext.Current.Web.CurrentUser.LoginName;
        }

        public static int GenerateTagCloudFontSize(decimal tagCount, decimal maxCount)
        {
            decimal fontSize = 0;

            fontSize = tagCount / maxCount *
                (OCPConstant.MOHipedia.TagCloud.MaxFontSize - OCPConstant.MOHipedia.TagCloud.MinFontSize) +
                 OCPConstant.MOHipedia.TagCloud.MinFontSize;

            fontSize = Math.Round(fontSize);
            return int.Parse(fontSize.ToString());
        }

        /// <summary>
        /// Emailing module
        /// </summary>
        /// <param name="OCPapplication"></param>
        /// <param name="fromAddress">nullable, if null, will use default value</param>
        /// <param name="toAddress"></param>
        /// <param name="ccList"></param>
        /// <param name="recipientName"></param>
        /// <param name="eMailTemplateName"></param>
        public static void SendEMail(string applicationName, string emailType,
                                     string fromAddress, string toAddress, string[] ccList,
                                     Dictionary<string, string> replaceableKV)
        {
            if (string.IsNullOrEmpty(fromAddress))
            {
                fromAddress = SPContext.Current.Site.WebApplication.OutboundMailSenderAddress;
            }

            SPItem oItem = GetMailTemplate(applicationName, emailType);
            string subject = oItem["EMAIL_SUBJECT"].ToString();
            string body = SPEncode.HtmlDecode(oItem["EMAIL_CONTENT"].ToString());

            foreach (string key in replaceableKV.Keys)
            {
                body = body.Replace(key, replaceableKV[key]);
            }
            if (ccList == null)
                SendEmail(fromAddress, toAddress, null, subject, body);
            else
                SendEmail(fromAddress, toAddress, ccList, subject, body);
        }

        private static SPItem GetMailTemplate(string applicationName, string emailType)
        {
            SPListItemCollection oListItemColl = null;
            string OCPUrl = ConfigurationSettings.AppSettings["OCPUrl"];
            SPSecurity.RunWithElevatedPrivileges(delegate()
           {
               using (SPSite site = new SPSite(OCPUrl))
               {
                   //using (SPWeb web = site.RootWeb)
                   using (SPWeb web = site.OpenWeb())
                   {
                       SPList oList = web.GetList("/Lists/EmailTemplate");
                       SPQuery query = new SPQuery();
                       query.Query = "<Where>" +
                                         "<And>" +
                                            "<Eq>" +
                                               "<FieldRef Name=\"APP_NAME\" />" +
                                               "<Value Type=\"Text\">" + applicationName + "</Value>" +
                                            "</Eq>" +
                                            "<Eq>" +
                                               "<FieldRef Name=\"EMAIL_TYPE\" />" +
                                               "<Value Type=\"Text\">" + emailType + "</Value>" +
                                            "</Eq>" +
                                         "</And>" +
                                      "</Where>";
                       query.RowLimit = 1;
                       oListItemColl = oList.GetItems(query);
                   }
               }
           });
            return oListItemColl[0];
        }

        private static void SendEmail(string from, string to, string[] ccTo, string subject, string body)
        {
            if (to.TrimEnd(';').Trim() != "")
            {
                MailMessage mailMsg = new MailMessage();

                mailMsg.Subject = subject;
                mailMsg.Body = body;
                mailMsg.IsBodyHtml = true;
                mailMsg.From = new MailAddress(from);
                string[] mailTo = to.Split(';');
                foreach (string str in mailTo)
                {
                    if (str.Trim() != "")
                        mailMsg.To.Add(str.Trim());
                }

                SmtpClient client = new SmtpClient();
                client.Host = SPContext.Current.Web.Site.WebApplication.OutboundMailServiceInstance.Server.Address;
                client.Send(mailMsg);
            }
        }

    }
}
